
#include "Framework.h"
#include <sys/types.h>
#include <sys/times.h>
#include <unistd.h>
#include <errno.h>
#include <vector>
#include <string>
using namespace std;

/* constructor */
TFW_EventDispatcher::TFW_EventDispatcher()
{
	
}

TFW_EventDispatcher::~TFW_EventDispatcher(){}

/* initialize status */
void TFW_EventDispatcher::initialize()
{
	/* initialize status */
		/* walkup pipe */
	int rtn = pipe(m_WalkupSelectPipe);
	if(rtn < 0)
	{
		/* log write */
		cout<<"pipe failure :" <<errno<<endl;
		return ;
	}
	
	else
	{
		m_WalkupPipeForWrite = m_WalkupSelectPipe[1];
		m_WalkupPipeForRead = m_WalkupSelectPipe[0];
	}
}

/* register for eventqueue */
void TFW_EventDispatcher::registEventQueue(TFW_EventQueue* eventqueue)
{
	m_eventqueueTable.push_back(eventqueue);
}

/* remove registed event queue */
void TFW_EventDispatcher::removeEventQueue(TFW_EventQueue* eventqueue)
{
	m_eventqueueTable.erase(find(m_eventqueueTable.begin(), m_eventqueueTable.end(), eventqueue));
}

/* mainloop */
void TFW_EventDispatcher::mainloop()
{
	/* max descriptor */
	int maxdp ;
	fd_set rset;
	bool fQuit;
	TFW_Event* evt;
	struct timeval* timeTO;
	struct timeval no_wait = {0, 0};
	bool fNoWait = false;
	
	/* initialize */
	FD_ZERO(&rset);
	fQuit = false;
	while(!fQuit)
	{
		/* walk up pipe descriptor */
		maxdp = max(maxdp, m_WalkupPipeForRead);
		FD_SET(m_WalkupPipeForRead, &rset);
		
		/* set event queue */
		for(size_t index; index < m_eventqueueTable.size(); index++)
		{
			maxdp = max(maxdp, m_eventqueueTable[index]->getFd());
			FD_SET(m_eventqueueTable[index]->getFd(), &rset);
		}
		
		timeTO = fNoWait ? &no_wait : NULL;
		
		int rtn = select(maxdp+1, &rset, NULL, NULL, timeTO);
		if(rtn < 0)
		{
			cout<<"select failure :"<<errno<<endl;
			continue;
		}
		/* first: check walkupSingle */
		if(FD_ISSET(m_WalkupPipeForRead, &rset))
		{
			fQuit = true;
			continue;
		}
		
		/* second: check event queue */
		for(size_t index = 0; index < m_eventqueueTable.size(); index ++)
		{
			evt = m_eventqueueTable[index]->peekEvent();
			if(NULL == evt)
			{
				continue;
			}
			
			m_eventqueueTable[index]->handleEvent(evt);
			
			delete evt;
		}
	}
}

/* stop */
void TFW_EventDispatcher::stop()
{
	/* walkup */
	write(m_WalkupPipeForWrite, (char*)1, sizeof(int));
}
